// Copyright (C) 2023 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
// 
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<北京小羊驼科技有限公司>，授权编号：<NT231212144350>，代码指纹：<A.702363430.550>，技术对接人微信：<ID: wxid_wbyootvkdcgj22>】
// 【授权寄送：<收件：苏先生、地址：北京市大兴区北京密码西区6号楼1单元301、电话：18613885610、邮箱：bd@huiyuanxiang-inc.com>】
// 
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
// 
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.eva.framework.utils;

import java.util.Vector;

import com.eva.epc.common.util.CommonUtils;
import com.eva.framework.dbpool.DBShell;

/**
 * 序列号(serial number)生成实现类.<br>
 * 获取序列号并完成对序列配置信息的数据库更新操作.<br>
 * 单号生成规则定义于数据库表esys_sn里.
 * 
 * @author Jack Jiang(http://www.52im.net/space-uid-1.html)
 * @version 1.0
 */
public class SNHelper
{
	/** 系列号生成配置信息存放表名 */
	private static String snConfTableName = "esys_sn";//TableConst.DEFAULT_T_SYS_SERIAL_GEN;
	/** 数据库操作实用类 */
	private static DBShell db = new DBShell();

	/**
	 * 按默认值指定属性构造对象
	 */
	public SNHelper()
	{
		this(snConfTableName);
	}
	/**
	 * 按指定属性构造对象
	 * 
	 * @param tableName 序列号配置信息数据库表名
	 */
	public SNHelper(String tableName)
	{
		setSNConfTableName(tableName);
		db = new DBShell();
	}

	/**
	 * 按数据库配置中的序列名获取序列号，支持一次获取多个序列号（是连续的）.
	 * 
	 * @param snName 存放序列号配置表中的要取的序列名
	 * @param count 要取的个数（一般情况下会是1，支持多个序列号一次生成，1～N）
	 * @return 返回生成的序列号数组，数组长度=count
	 */
	public static synchronized String[] getMultiSN(String snName,int count)
	{
		//最后的编号
		String[] sequence = new String[count];
		//编号当前值
		long currentValue = -1;
		//最小值
		long minValue = -1;
		//最大值
		long maxValue = -1;
		//编号位数
		int digit = -1;
		//编号规则
		String appendStr = "";

		//构造查询语句
		StringBuffer sql = new StringBuffer().append(
				"select "+ESYS_SN.current_val+","+ESYS_SN.min_val+","
						+ESYS_SN.max_val+","+ESYS_SN.digit+","+ESYS_SN.head_str+" from ")
					.append(snConfTableName)
					.append(" where "+ESYS_SN.sn_name+" = '")
					.append(snName)
					.append("'");
		try
		{
			//获取当前序列号值，最小值，最大值，位数
			Vector returnValue = db.queryData(sql.toString());
			returnValue = (Vector)returnValue.elementAt(0);
			currentValue = Long.parseLong(returnValue.elementAt(0).toString());
			minValue = Long.parseLong(returnValue.elementAt(1).toString());
			maxValue = Long.parseLong(returnValue.elementAt(2).toString());
			digit = Integer.parseInt(returnValue.elementAt(3).toString());
			appendStr = returnValue.elementAt(4).toString();
			
			//不合理（当前生成的序列号超过了配置时定的最大值 和最小值边界了）
			if((currentValue+count)>maxValue || currentValue<minValue)
			{
				StringBuilder sb = new StringBuilder();
				sb.append("生成的序列号越界了，(")
				.append(currentValue).append("+").append(count).append(")>")
				.append(maxValue).append(" || ").append(currentValue).append("<")
				.append(minValue).append(",snName=").append(snName).append(" count=").append(count);
				LoggerFactory.getLog().warn(sb.toString());
			}
			//合理，更新当前值
			else
			{
				//currentValue++;
				currentValue+=count;
				sql = new StringBuffer()
					.append("update ").append(snConfTableName)
					.append(" set "+ESYS_SN.current_val+"=?")
					.append(" where "+ESYS_SN.sn_name+"=?");
				try{
					db.update(sql.toString(), new Object[]{currentValue,snName}, true);
					sequence = CommonUtils.sequence(currentValue-count,count,digit,appendStr);
				}
				catch (Exception e){
					LoggerFactory.getLog().warn("执行SQL="+sql+"时出错,"+e.getMessage());
				}
			}
		}
		catch(Exception ex){
			LoggerFactory.getLog().warn(ex.getMessage(),ex);
		}
		return sequence;
	}
	/**
	 * 按数据库配置中的序列名获取序列号，一次获取一个序列号.
	 * 
	 * @param numberName 据库配置中的序列名
	 * @return 得到的序列号，如为""则表示出错了
	 */
	public static synchronized String getSN(String numberName)
	{
		String[] seq = getMultiSN(numberName,1);
		if(seq[0]==null)
		{
			seq[0]="";
			LoggerFactory.getLog().warn("获取一个序列号失败,numberName="+numberName);
		}
		return seq[0];
	}
	
	public static String getSNConfTableName()
	{
		return snConfTableName;
	}
	public static void setSNConfTableName(String snConfTableName)
	{
		SNHelper.snConfTableName = snConfTableName;
	}
	
	// 数据库表esys_sn表字段定义（与数据库中的表字段严格对应，请保持一致！）
	public interface ESYS_SN
	{
		String sn_name = "sn_name";
		String current_val = "current_val";
		String min_val = "min_val";
		String max_val = "max_val";
		String digit = "digit";
		String head_str = "head_str";
		String bz = "bz";
		String gen_time = "gen_time";
	}
}